﻿using System;
using System.Collections.Generic;
using System.Text;

namespace OkTool.Codec
{
    public class Base16Codec
    {
        public static  Base16Codec CODEC_LOWER = new Base16Codec(true);
        public static  Base16Codec CODEC_UPPER = new Base16Codec(false);


        private  char[] alphabets;
        /// <summary>
        /// 是否小写
        /// </summary>
        /// <param name="lowerCase"></param>
        public Base16Codec(bool lowerCase)
        {
            this.alphabets = (lowerCase ? "0123456789abcdef" : "0123456789ABCDEF").ToCharArray();
        }


        /// <summary>
        /// 将byte值转为16进制并添加到{@link StringBuilder}中
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="b"></param>
        public void AppendHex(StringBuilder builder, byte b)
        {
            int high = (b & 0xf0) >> 4; // 高位
            int low = b & 0x0f; // 低位
            builder.Append(alphabets[high]);
            builder.Append(alphabets[low]);
        }


        /// <summary>
        /// 将指定char值转换为Unicode字符串形式，常用于特殊字符（例如汉字）转Unicode形式
        ///<para> 转换的字符串如果u后不足4位，则前面用0填充，例如：'你' =》'\u4f60'</para>
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public string ToUnicodeHex(char ch)
        {
            return "\\u" +
                alphabets[(ch >> 12) & 15] +
                alphabets[(ch >> 8) & 15] +
                alphabets[(ch >> 4) & 15] +
                alphabets[ch & 15];
        }
        public char[] Encode(byte[] data)
        {
            int len = data.Length;
            char[] outp = new char[len << 1]; // len * 2
                                              // two characters from the hex value.
            for (int i = 0, j = 0; i < len; i++)
            {
                outp[j++] = alphabets[(0xF0 & data[i]) >> 4]; // 高位
                outp[j++] = alphabets[0x0F & data[i]]; // 低位
            }
            return outp;
        }

        public byte[] Decode(string encoded)
        {
            if (string.IsNullOrEmpty(encoded))
            {
                return null;
            }

            encoded = encoded.Replace(" ", ""); // 清除空格
            int len = encoded.Length;

            if ((len & 0x01) != 0)
            {
                // 如果提供的数据是奇数长度，则前面补0凑偶数
                encoded = "0" + encoded;
                len = encoded.Length;
            }

            byte[] outBytes = new byte[len >> 1];

            // two characters form the hex value.
            for (int i = 0, j = 0; j < len; i++)
            {
                int f = ToDigit(encoded[j], j) << 4;
                j++;
                f = f | ToDigit(encoded[j], j);
                j++;
                outBytes[i] = (byte)(f & 0xFF);
            }

            return outBytes;
        }

        private int ToDigit(char ch, int index)
        {
            int digit = char.IsDigit(ch) ? ch - '0' : char.ToLower(ch) - 'a' + 10;
            if (digit < 0 || digit >= 16)
            {
                throw new ArgumentException("Invalid hex digit '" + ch + "' at index " + index);
            }
            return digit;
        }
    }
}
